#include "storage_manager_impl.h"
#include <mutex>
#include <sstream>
#include <iostream>
#include "storage_device_impl.h"
#include "base_log.h"
#include "common_config_manager.h"

namespace El {
namespace Storage {

IStorageManager &IStorageManager::GetInstance()
{
    static StorageManagerImpl instance;
    return instance;
}

StorageManagerImpl::StorageManagerImpl()
{
    // 监听配置变化
    listenerId_ = Common::ConfigManager::GetInstance().RegisterVerify("storage", [this](const nlohmann::json &config) {
        LOG_INFO("storage config changed: {}", config.dump().c_str());
        storageConfig_ = config;
        return true;
    });

    // 读取配置文件
    storageConfig_ = Common::ConfigManager::GetInstance().GetConfig("storage");
    if (!storageConfig_.empty() && storageConfig_.contains("mountPath") &&
        storageConfig_.contains("warningThreshold") && storageConfig_.contains("reserveSpace")) {
        mountPath_ = storageConfig_["mountPath"].get<std::string>();
        warningThreshold_ = storageConfig_["warningThreshold"].get<uint32_t>();
        reserveSpace_ = storageConfig_["reserveSpace"].get<uint32_t>();
    } else {
        mountPath_ = "/mnt/udisk";
        warningThreshold_ = 95;
        reserveSpace_ = 100;
        LOG_ERROR("storage config is empty");
    }
    LOG_INFO("storage config: mountPath {} warningThreshold {} reserveSpace {}", mountPath_, warningThreshold_,
             reserveSpace_);
}

StorageManagerImpl::~StorageManagerImpl()
{
    Stop();
    Common::ConfigManager::GetInstance().UnregisterVerify("storage", listenerId_);
}

bool StorageManagerImpl::Start()
{
    StartMonitoring();
    return true;
}

void StorageManagerImpl::Stop()
{
    StopMonitoring();
}

std::shared_ptr<IStorageDevice> StorageManagerImpl::GetDevice(std::string_view devicePath)
{
    std::lock_guard<std::mutex> lock(devicesMutex_);
    auto it = devices_.find(std::string(devicePath));
    return (it != devices_.end()) ? it->second : nullptr;
}

bool StorageManagerImpl::RemoveDevice(std::string devicePath)
{
    RemoveDeviceInternal(devicePath);
    return true;
}

StorageCapacity StorageManagerImpl::GetTotalCapacity() const
{
    std::lock_guard<std::mutex> lock(devicesMutex_);
    StorageCapacity total{};

    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device->GetStatus() == DeviceStatus::ERR_MOUNTED) {
            auto capacity = device->GetCapacity();
            total.totalBytes += capacity.totalBytes;
            total.usedBytes += capacity.usedBytes;
            total.availableBytes += capacity.availableBytes;
        }
    }

    if (total.totalBytes > 0) {
        total.usagePercentage = static_cast<int32_t>(total.usedBytes * 100 / total.totalBytes);
    }

    return total;
}

bool StorageManagerImpl::CleanupSpace(uint64_t requiredBytes)
{
    (void)requiredBytes; // 避免未使用参数警告
    LOG_ERROR("CleanupSpace not implemented");
    return false;
}

uint32_t StorageManagerImpl::RegisterStorageEventCallback(StorageEventCallback callback)
{
    std::lock_guard<std::mutex> lock(callbackMutex_);
    uint32_t callbackId = nextCallbackId_++;
    storageEventCallbacks_[callbackId] = std::move(callback);
    return callbackId;
}

bool StorageManagerImpl::UnregisterStorageEventCallback(uint32_t callbackId)
{
    std::lock_guard<std::mutex> lock(callbackMutex_);
    return storageEventCallbacks_.erase(callbackId) > 0;
}

void StorageManagerImpl::StartMonitoring()
{
    udev_ = udev_new();
    if (!udev_) {
        throw std::runtime_error("Failed to initialize udev");
    }

    stopMonitoring_ = false;
    monitorThread_ = std::thread(&StorageManagerImpl::MonitorDevices, this);
}

void StorageManagerImpl::StopMonitoring()
{
    stopMonitoring_ = true;
    if (monitorThread_.joinable()) {
        monitorThread_.join();
    }

    if (udev_) {
        udev_unref(udev_);
        udev_ = nullptr;
    }
}

void StorageManagerImpl::MonitorDevices()
{
    // 先枚举现有设备
    EnumerateExistingDevices();

    // 设置udev监视器
    struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev_, "udev");
    if (!monitor) {
        LOG_ERROR("Failed to create udev monitor");
        return;
    }
    udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", nullptr);
    udev_monitor_enable_receiving(monitor);

    int fd = udev_monitor_get_fd(monitor);

    while (!stopMonitoring_) {
        fd_set fds;
        struct timeval tv;
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        tv.tv_sec = 1;
        tv.tv_usec = 0;

        int ret = select(fd + 1, &fds, nullptr, nullptr, &tv);
        if (ret > 0 && FD_ISSET(fd, &fds)) {
            struct udev_device *dev = udev_monitor_receive_device(monitor);
            if (dev) {
                std::string action = udev_device_get_action(dev);
                HandleDevice(dev, action);
                udev_device_unref(dev);
            }
        }

        CheckCapacityWarnings();
    }

    if (monitor) {
        udev_monitor_unref(monitor);
    }
}

void StorageManagerImpl::CheckCapacityWarnings()
{
    std::lock_guard<std::mutex> lock(devicesMutex_);

    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device->GetStatus() != DeviceStatus::ERR_MOUNTED) {
            continue;
        }

        auto capacity = device->GetCapacity();
        uint64_t availableMB = capacity.availableBytes / (1024 * 1024);
        if (availableMB <= (reserveSpace_ + 100)) {
            LOG_DEBUG("Storage space warning: device {} available {}MB below reserve {}MB", device->GetDevicePath(),
                      availableMB, (reserveSpace_ + 100));
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_WARNING);
        }

        bool isFull = false;
        if (availableMB <= reserveSpace_) {
            LOG_DEBUG("Storage space full: device {} available {}MB below reserve {}MB", device->GetDevicePath(),
                      availableMB, reserveSpace_);
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_FULL);
            isFull = true;
        }

        const std::string devicePath = device->GetDevicePath();
        bool wasInWarningState = deviceWarningStates_[devicePath];

        if (!isFull && wasInWarningState) {
            LOG_DEBUG("Storage space returned to normal: device {} available {}MB above reserve {}MB",
                      device->GetDevicePath(), availableMB, reserveSpace_);
            NotifyStorageEvent(device, DeviceStatus::ERR_CAPACITY_NORMAL);
        }

        deviceWarningStates_[devicePath] = isFull;
    }
}

void StorageManagerImpl::EnumerateExistingDevices()
{
    struct udev_enumerate *enumerate = udev_enumerate_new(udev_);
    if (!enumerate) {
        LOG_ERROR("Failed to create udev enumeration");
        return;
    }

    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_add_match_property(enumerate, "DEVTYPE", "disk");
    udev_enumerate_scan_devices(enumerate);

    struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
    struct udev_list_entry *entry;

    udev_list_entry_foreach(entry, devices)
    {
        const char *path = udev_list_entry_get_name(entry);
        struct udev_device *dev = udev_device_new_from_syspath(udev_, path);
        HandleDevice(dev, "add");
        if (dev) {
            udev_device_unref(dev);
        }
    }

    udev_enumerate_unref(enumerate);
}

void StorageManagerImpl::NotifyStorageEvent(const std::shared_ptr<IStorageDevice> &device, DeviceStatus status)
{
    LOG_DEBUG("NotifyStorageEvent: {} {}", device->GetDevicePath(), static_cast<int>(status));
    std::lock_guard<std::mutex> lock(callbackMutex_);
    for (const auto &[id, callback] : storageEventCallbacks_) {
        (void)id;
        if (callback) {
            callback(device, status);
        }
    }
}

DeviceType StorageManagerImpl::DetectDeviceType(struct udev_device *dev)
{
    std::string devnode = udev_device_get_devnode(dev);
    if (devnode.empty()) {
        return DeviceType::ERR_UNKNOWN;
    }

    // 获取关键设备属性
    const char *idBus = udev_device_get_property_value(dev, "ID_BUS");
    const char *idType = udev_device_get_property_value(dev, "ID_TYPE");
    const char *idPath = udev_device_get_property_value(dev, "ID_PATH");
    const char *devtype = udev_device_get_property_value(dev, "DEVTYPE");

    // 打印调试信息
    LOG_DEBUG("Device detection - Path: {}, Bus: {}, Type: {}", devnode, idBus ? idBus : "null",
              idType ? idType : "null");

    // 检查设备名称是否包含mmcblk
    if (devnode.find("mmcblk") != std::string::npos) {
        // 获取父设备以检查更多属性
        struct udev_device *parent = udev_device_get_parent(dev);
        if (parent) {
            const char *driver = udev_device_get_driver(parent);
            const char *subsystem = udev_device_get_subsystem(parent);

            LOG_DEBUG("MMC device detection - Driver: {}, Subsystem: {}", driver ? driver : "null",
                      subsystem ? subsystem : "null");

            // 检查是否为eMMC
            if (driver && (strcmp(driver, "mmcblk") == 0 || strcmp(driver, "mmc_block") == 0)) {
                if (devnode.find("mmcblk0") != std::string::npos) {
                    LOG_INFO("Detected eMMC device: {}", devnode);
                    return DeviceType::EMMC_NAND;
                } else {
                    LOG_INFO("Detected SD card: {}", devnode);
                    return DeviceType::SD_CARD;
                }
            }
        }

        // 如果无法通过父设备判断，默认为SD卡
        LOG_INFO("Detected SD card (default): {}", devnode);
        return DeviceType::SD_CARD;
    }

    // 设备类型检测
    // SD卡检测 (保留原有的mmc总线检测逻辑作为备选)
    if (idBus && strcmp(idBus, "mmc") == 0) {
        // 检查是否为内置eMMC
        if (idPath && strstr(idPath, "platform-") != nullptr) {
            LOG_INFO("Detected eMMC device: {}", devnode);
            return DeviceType::EMMC_NAND;
        }
        LOG_INFO("Detected SD card: {}", devnode);
        return DeviceType::SD_CARD;
    }

    // USB存储设备检测
    if ((idBus && strcmp(idBus, "usb") == 0)) {
        if (devtype && strcmp(devtype, "disk") == 0) {
            LOG_INFO("Detected USB drive: {}", devnode);
            return DeviceType::USB_DRIVE;
        }
    }

    LOG_DEBUG("Unknown device type: {}", devnode);
    return DeviceType::ERR_UNKNOWN;
}

bool StorageManagerImpl::AddAndMountDevice(const std::string &devpath, DeviceType deviceType)
{
    auto device = StorageDeviceImpl::CreateStorageDevice(deviceType, devpath, mountPath_);
    if (!device) {
        LOG_ERROR("Failed to create storage device for {}", devpath);
        return false;
    }

    {
        std::lock_guard<std::mutex> lock(devicesMutex_);
        devices_[devpath] = device;
        deviceWarningStates_[devpath] = false; // 初始化为非警告状态
    }

    NotifyStorageEvent(device, DeviceStatus::ERR_DEVICE_ADDED);

    if (device->Mount()) {
        NotifyStorageEvent(device, DeviceStatus::ERR_MOUNTED);
        return true;
    }

    LOG_ERROR("Failed to mount device {}", devpath);
    return false;
}

void StorageManagerImpl::RemoveDeviceInternal(const std::string &devpath)
{
    auto device = GetDevice(devpath);
    if (!device) {
        LOG_ERROR("Device not found: {}", devpath);
        return;
    }

    device->Unmount();
    NotifyStorageEvent(device, DeviceStatus::ERR_UNMOUNTED);
    {
        std::lock_guard<std::mutex> lock(devicesMutex_);
        devices_.erase(devpath);
        deviceWarningStates_.erase(devpath); // 清理警告状态
    }
    LOG_INFO("Device unmounted: {}", devpath);

    NotifyStorageEvent(device, DeviceStatus::ERR_DEVICE_REMOVED);
    LOG_INFO("Device removed: {}", devpath);
}

void StorageManagerImpl::HandleDevice(struct udev_device *dev, std::string action)
{
    if (!dev) {
        return;
    }

    std::string devpath = udev_device_get_devnode(dev);
    if (devpath.empty()) {
        return;
    }

    DeviceType deviceType = DetectDeviceType(dev);
    if (deviceType == DeviceType::ERR_UNKNOWN) {
        return;
    }

    if (action == "add") {
        AddAndMountDevice(devpath, deviceType);
    } else if (action == "remove") {
        RemoveDeviceInternal(devpath);
    }
}

bool StorageManagerImpl::GetDefaultUdiskStatus(DeviceStatus &status)
{
    std::lock_guard<std::mutex> lock(devicesMutex_);

    // 遍历所有设备，查找USB_DRIVE类型的设备
    for (const auto &[path, device] : devices_) {
        (void)path;
        if (device) {
            status = device->GetStatus();
            return true;
        }
    }

    // 如果没有找到USB设备，返回NOT_EXIST状态
    status = DeviceStatus::ERR_NOT_EXIST;
    return false;
}

} // namespace Storage
} // namespace El